home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / comm / bbs / s342q16.lha / msgadd.c < prev    next >
C/C++ Source or Header  |  1996-09-05  |  32KB  |  1,311 lines

  1. /*
  2.  *                              msgadd.c
  3.  *
  4.  * External Message handler.  For use with external OtherNet parsers.
  5.  */
  6.  
  7. /*
  8.  *                              history
  9.  *
  10.  * 96Sep01 AFP  V1.5 -- support vortex checking and archiving by month & year
  11.  * 91Mar31 HAW  v1.4 -- support for virtual rooms.
  12.  * 90Aug13 HAW  v1.3 -- support for room archiving.
  13.  * 89Oct23 HAW  v1.2 -- support for incoming route mail.
  14.  * 88Nov05 HAW  Created.
  15.  */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "ctdl.h"
  19. #include "math.h"
  20. /*
  21.  *                              contents
  22.  *
  23.  */
  24.  
  25. #define TITLE           "C86Net Message Adder(Amiga)"
  26. #define VERSION         "V3.42"
  27.  
  28. #define NO_ERROR        0
  29. #define BAD_ARGS        1
  30. #define BAD_TABLE       2
  31. #define NO_NODE         3
  32. #define FATAL           4
  33. #define LF_ERROR        5
  34.  
  35. int crtColumn;
  36. extern CONFIG      cfg;         /* Configuration variables      */
  37. extern MessageBuffer     msgBuf;        /* The -sole- message buffer    */
  38. extern aRoom       roomBuf;     /* Room buffer  */
  39. extern logBuffer   logBuf;
  40. extern FILE     *roomfl, *logfl;
  41. extern int      thisRoom;       /* Current room */
  42. extern rTable      *roomTab;
  43. extern struct mBuf mFile1, mFile2;
  44. extern NetTable    *netTab;
  45. extern NetBuffer   netBuf;
  46. extern NetBuffer   netTemp;
  47. extern FILE     *netfl;
  48. extern LogTable    *logTab;
  49. extern int      thisNet;        /* Current node in use  */
  50. extern char     *APPEND_ANY;
  51. extern char     *APPEND_TEXT;
  52. extern FILE     *msgfl, *msgfl2;
  53. FILE    *GlobalFd;
  54. int     RouteSlot;
  55. extern FILE *upfd;
  56. char inNet = NORMAL_NET;
  57.  
  58. FILE      *netLog = NULL;
  59. char logNetResults = 1;
  60. char netDebug = 1;
  61.  
  62.  
  63. SListBase MailForward = { NULL, NULL, NULL, NULL, NULL };
  64. SListBase  Arch_base = { NULL, ChkNtoStr, NULL, FreeNtoStr, EatNMapStr };
  65. static char EOP = FALSE;
  66. char *R_SH_MARK =  "&&";
  67. char *NON_LOC_NET= "%%";
  68. char *LOC_NET =    "++";
  69.  
  70. #ifdef ANSI_PROTOTYPING
  71.  
  72. void GenInit(void);
  73. void Process(char *fn);
  74. int  GetOtherNetChar(void);
  75. int VirtualShared(int NetNo, label name);
  76. int VirtualExists(label name);
  77. void SaveIt(void);
  78. int  FindPerson(label nm, logBuffer *lbuf);
  79. int  FindRoom(label nm);
  80. int  FindNet(label nm, NetBuffer *netBuf);
  81. void AddVirtualField(char field, char *contents);
  82. void PutMessage(void);
  83. void HandleRouted(void);
  84. void AddField(int field, char *fValue);
  85. int  FindPos(void);
  86. void VirtualHandle(void);
  87. int MARecVirtualRoom(int VirtIndex);
  88. void TranslateFilename(char *realfn, char *fn);
  89. void netResult(char *);
  90. #endif
  91.  
  92. int  mPrintf(char *format, ...) {return 0; }  /* stub to quiet the linker */
  93.  
  94.  
  95. /*
  96.  * crashout()
  97.  *
  98.  * Big error handler.
  99.  */
  100. void crashout(str)
  101. char *str;
  102. {
  103.     printf(str);
  104.     exit(FATAL);
  105. }
  106.  
  107. /*
  108.  * main()
  109.  *
  110.  * This is the main manager.
  111.  */
  112. int  main(int, char **);
  113. int  main(argc, argv)
  114. char **argv;
  115. int  argc;
  116. {
  117.     int rover;
  118.  
  119.     printf("%s %s\n%s\n\n", TITLE, VERSION, COPYRIGHT);
  120.  
  121.     /* not enough arguments?  Explain. */
  122.     if (argc < 3) {
  123.         printf("usage: MSGADD nodename file [ file ... ]\n");
  124.         printf("\nEach file may contain one or more messages in C86Net format.\n");
  125.         exit(BAD_ARGS);
  126.     }
  127.  
  128.     cfg.weAre = UTILITY;
  129.     if (!readSysTab(TRUE, TRUE)) {
  130.         exit(BAD_TABLE);
  131.     }
  132.  
  133.     if (access(LOCKFILE, 0) != -1) {
  134.         printf("Please do not run MsgAdd using Outside Commands.\n");
  135.         writeSysTab();
  136.         exit(LF_ERROR);
  137.     }
  138.  
  139.     GenInit();
  140.  
  141.     VirtInit();
  142.  
  143.     if (FindNet(argv[1], &netBuf) == ERROR) {
  144.         writeSysTab();
  145.         printf("Could not find node %s.\n", argv[1]);
  146.         exit(NO_NODE);
  147.     }
  148.  
  149.     for (rover = 2; rover < argc; rover++)
  150.         Process(argv[rover]);
  151.  
  152.     UpdVirtStuff();
  153.     writeSysTab();
  154.   return 0;
  155.   }
  156.  
  157. /*
  158.  * GenInit()
  159.  *
  160.  * This is a general initialization routine.
  161.  */
  162. void GenInit()
  163. {
  164.     SYS_FILE fn;
  165.  
  166.     initNetBuf(&netBuf);
  167.     initNetBuf(&netTemp);
  168.     makeSysName(fn, "ctdlnet.sys", &cfg.netArea);
  169.     openFile(fn, &netfl);
  170.  
  171.     initRoomBuf(&roomBuf);
  172.     makeSysName(fn, "ctdlroom.sys", &cfg.roomArea);
  173.     openFile(fn, &roomfl);
  174.  
  175.     InitMsgBase();
  176.  
  177.     initLogBuf(&logBuf);
  178.     makeSysName(fn, "ctdllog.sys", &cfg.logArea);
  179.     openFile(fn, &logfl);
  180.  
  181.     makeSysName(fn, "ctdlarch.sys", &cfg.roomArea);
  182.     MakeList(&Arch_base, fn, NULL);
  183. }
  184.  
  185. /*
  186.  * Process()
  187.  *
  188.  * This will process a file - read a file for all messages and stuff them
  189.  * into the message base.
  190.  */
  191. void Process(fn)
  192. char *fn;
  193. {
  194.     extern char *READ_ANY;
  195.  
  196.     if ((GlobalFd = fopen(fn, READ_ANY)) == NULL) {
  197.         printf("ERROR: Could not open %s.\n", fn);
  198.         return;
  199.     }
  200.  
  201.     while (getMessage(GetOtherNetChar, TRUE, TRUE, TRUE))
  202.         SaveIt();
  203.  
  204.     fclose(GlobalFd);
  205. }
  206.  
  207. /*
  208.  * GetOtherNetChar()
  209.  *
  210.  * This gets a character for getMessage.
  211.  */
  212. int GetOtherNetChar()
  213. {
  214.     int c;
  215.  
  216.     c = getc(GlobalFd);
  217.     if (c == EOF) return -1;
  218.     return c;
  219. }
  220.  
  221. /*
  222.  * SaveIt()
  223.  *
  224.  * This is charged with saving the message in the database.
  225.  *
  226.  * 1. If mail, must do recipient validation.
  227.  * 2. Must validate room.
  228.  */
  229. void SaveIt()
  230. {
  231.     int LogSlot, RoomSlot, place;
  232.     extern char *NON_LOC_NET, *LOC_NET;
  233.     char *fn, *realfn;
  234.     char header[200];
  235.  
  236. #ifdef VIEWING
  237.     printf("mbauth=-%s-\n", msgBuf.mbauth);
  238.     printf("mbroom=-%s-\n", msgBuf.mbroom);
  239.     printf("mbdate=-%s-\n", msgBuf.mbdate);
  240.     printf("mbtime=-%s-\n", msgBuf.mbtime);
  241.     printf("mboname=-%s-\n", msgBuf.mboname);
  242.     printf("mborig=-%s-\n", msgBuf.mborig);
  243.     printf("mbto=-%s-\n", msgBuf.mbto);
  244.     printf("mbsrcId=-%s-\n", msgBuf.mbsrcId);
  245.     printf("mbtext=-%s-\n", msgBuf.mbtext);
  246.     printf("\n");
  247. #endif
  248.  
  249.     if (VirtualExists(msgBuf.mbroom) != ERROR) {
  250.         VirtualHandle();
  251.         return ;
  252.     }
  253.  
  254.     if (strLen(msgBuf.mbaddr) != 0) {
  255.         HandleRouted();
  256.     }
  257.     else if (strCmpU(msgBuf.mbroom, "mail") == SAMESTRING) {
  258.         if ((LogSlot = FindPerson(msgBuf.mbto, &logBuf)) == ERROR) {
  259.             printf("Could not deliver Mail to '%s', does not exist.\n",
  260.                                                         msgBuf.mbto);
  261.             return ;
  262.         }
  263.         noteAMessage(logBuf.lbMail, MAILSLOTS, cfg.newest+1, cfg.catSector);
  264.         putLog(&logBuf, LogSlot);
  265.     }
  266.     else {
  267.         if ((RoomSlot = FindRoom(msgBuf.mbroom)) == ERROR) {
  268.             printf("Message meant for non-existent room '%s' not incorporated.\n",
  269.                                                 msgBuf.mbroom);
  270.             return ;
  271.         };
  272.         if( ! NotVortex() )
  273.           {
  274.           printf("Message is a duplicate, not inorporated.\n");
  275.           printf("Author:%20s ", msgBuf.mbauth);
  276.           printf("Room:%s\n", msgBuf.mbroom);
  277.           printf("  date:%20s ", msgBuf.mbdate);
  278.           printf("time:%s\n", msgBuf.mbtime);
  279.           printf(" Oname:%20s ", msgBuf.mboname);
  280.           printf("orig:%s\n", msgBuf.mborig);
  281.           printf("    to:%20s ", msgBuf.mbto);
  282.           printf(" src:%s\n", msgBuf.mbsrcId);
  283.           return;
  284.           };
  285.         noteAMessage(roomBuf.msg, MSGSPERRM, cfg.newest+1, cfg.catSector);
  286.         roomTab[RoomSlot].rtlastMessage = cfg.newest + 1;
  287.         putRoom(RoomSlot);
  288.         if ((place = FindPos()) == ERROR)
  289.             printf("WARNING: msg for %s is not formally shared.\n",
  290.                                                         msgBuf.mbroom);
  291.  
  292.         if (roomBuf.rbShareType != PEON &&
  293.                                 netBuf.netRooms[place].mode != PEON)
  294.             strCpy(msgBuf.mbaddr, NON_LOC_NET);
  295.         else
  296.             strCpy(msgBuf.mbaddr, LOC_NET);
  297.  
  298.         if (roomBuf.rbflags.ARCHIVE == 1) {
  299.             fn = SearchList(&Arch_base, NtoStrInit(thisRoom, "", 0, TRUE));
  300.             realfn = GetDynamic(strlen(fn) + 15);
  301.             TranslateFilename(realfn,fn);
  302.             if ((upfd = fopen(fn, APPEND_TEXT)) != NULL) {
  303.                 header[0] = 0;
  304.                 if (msgBuf.mbdate[ 0])
  305.                     sPrintf(lbyte(header), "   %s ", msgBuf.mbdate);
  306.                 if (msgBuf.mbtime[ 0] && sendTime)
  307.                     sPrintf(lbyte(header), "%s ", msgBuf.mbtime);
  308.                 if (msgBuf.mbauth[ 0]) {
  309.                     sPrintf(lbyte(header), "from %s",    msgBuf.mbauth );
  310.                 }
  311.                 NormStr(msgBuf.mboname);
  312.                 if (msgBuf.mboname[0]) {
  313.                     sPrintf(lbyte(header), " @ %s", msgBuf.mboname);
  314.                     if (msgBuf.mbdomain[0])
  315.                         sPrintf(lbyte(header), cfg.DomainDisplay,
  316.                                                         msgBuf.mbdomain);
  317.                 }
  318.  
  319.                 if (msgBuf.mbto[   0]) {
  320.                     sPrintf(lbyte(header), " to %s", msgBuf.mbto);
  321.                 }
  322.                 fprintf(upfd, "%s\n", header);
  323.                 crtColumn = 1;
  324.                 mFormat(msgBuf.mbtext);
  325.                 fprintf(upfd, "\n");
  326.                 fclose(upfd);
  327.             }
  328.         }
  329.     }
  330.     strCpy(msgBuf.mborig, netBuf.netId);
  331.     PutMessage();
  332.     cfg.newest++;
  333.  
  334.     cfg.catSector   = mFile1.thisSector;
  335.     cfg.catChar     = mFile1.thisChar;
  336. }
  337.  
  338. SListBase FwdAliasii;   /* keeps some other stuff happy */
  339. char onConsole = FALSE, remoteSysop = FALSE;
  340. int  callSlot = ERROR;
  341. /*
  342.  * HandleRouted()
  343.  *
  344.  * This should handle mail routing incoming.
  345.  */
  346. void HandleRouted()
  347. {
  348.     char     *AltName;
  349.     label    Name, Id, temp;
  350.     SYS_FILE fn;
  351.     extern void (*NetPrintTarget)(char *fmt, ...);
  352.     extern int  (*ToFileWork)();
  353.  
  354.     /* no find? */
  355.     if ((RouteSlot = FindNet(msgBuf.mbaddr, &netTemp)) == ERROR) {
  356.         return;
  357.     }
  358.  
  359.     /* yes, found, data in netTemp - will we do the routing? */
  360.     if (!cfg.BoolFlags.RouteMail || !netTemp.nbflags.RouteTo) {
  361.         return;
  362.     }
  363.  
  364.     /* yes, we'll do the routing.  Now to figure it out. */
  365.     strCpy(Name, netTemp.netName);
  366.     strCpy(Id, netTemp.netId);
  367.  
  368.     if ((AltName = UseNetAlias(Name, TRUE)) != NULL)
  369.         strCpy(Name, AltName);
  370.  
  371.     if (FindRouteSlot() == ERROR) {
  372.         return;
  373.     }
  374.  
  375.         /* Ugly ugly kludge until we figure out how nbHiRouteInd is wrong */
  376.     if (netTemp.nbHiRouteInd < 0) netTemp.nbHiRouteInd = 0;
  377.     sPrintf(temp, "R%d.%d", RouteSlot, netTemp.nbHiRouteInd++);
  378.  
  379.     makeSysName(fn, temp, &cfg.netArea);
  380.  
  381.     if ((upfd = safeopen(fn, APPEND_ANY)) == NULL) {
  382.         return;
  383.     }
  384.  
  385.     fprintf(upfd, "%-20s", Id);
  386.     putc(0, upfd);
  387.     fprintf(upfd, "%-20s", Name);
  388.     putc(0, upfd);
  389.  
  390.     NetPrintTarget = ToFile;
  391.     StartEncode(putFLChar);
  392.     ToFileWork = Encode;
  393.     prNetStyle(TRUE, Encode, FALSE, "");
  394.     StopEncode();
  395.     fclose(upfd);
  396.     netTemp.nbflags.HasRouted = TRUE;
  397.  
  398.     putNet(RouteSlot, &netTemp);
  399. }
  400.  
  401. /*
  402.  * FindPerson()
  403.  *
  404.  * This loads the log record for the named person.
  405.  * RETURNS: ERROR if not found, else log record #
  406.  * (stolen from LOG.C)
  407.  */
  408. int FindPerson(name, lBuf)
  409. char      *name;
  410. logBuffer *lBuf;
  411. {
  412.     int  h, i, foundIt, logNo;
  413.  
  414.     if (strCmpU(name, "Citadel") != SAMESTRING) {
  415.         h   = hash(name);
  416.         for (foundIt = i = 0;  i < cfg.MAXLOGTAB && !foundIt;  i++) {
  417.             if (logTab[i].ltnmhash == h) {
  418.                 getLog(lBuf, logNo = logTab[i].ltlogSlot);
  419.                 if (lBuf->lbflags.L_INUSE &&
  420.                                 strCmpU(name, lBuf->lbname) == SAMESTRING) {
  421.                     foundIt = TRUE;
  422.                 }
  423.             }
  424.         }
  425.     }
  426.     else foundIt = FALSE;
  427.     if (!foundIt)    return ERROR;
  428.     else        return logNo;
  429. }
  430.  
  431. /*
  432.  * findRoom()
  433.  *
  434.  * This function should find the named room.  Return ERROR if not found.
  435.  */
  436. int FindRoom(nm)
  437. label nm;
  438. {
  439.     int rover;
  440.  
  441.     for (rover = 0; rover < MAXROOMS; rover++)
  442.         if (strCmpU(roomTab[rover].rtname, nm) == SAMESTRING) {
  443.             getRoom(rover);
  444.             return rover;
  445.         }
  446.  
  447.     return ERROR;
  448. }
  449.  
  450. /*
  451.  * noteAMessage()
  452.  *
  453.  * This function notes a message in a message array.  Stolen from MSG.C.
  454.  */
  455. void noteAMessage(base, slots, id, loc)
  456. MSG_NUMBER  id;
  457. SECTOR_ID   loc;
  458. theMessages *base;
  459. int     slots;
  460. {
  461.     int  i;
  462.  
  463.     /* store into current room: */
  464.     /* slide message pointers down to make room for this one:       */
  465.     for (i = 0;  i < slots - 1;  i++) {
  466.         base[i].rbmsgLoc  = base[i+1].rbmsgLoc;
  467.         base[i].rbmsgNo   = base[i+1].rbmsgNo ;
  468.     }
  469.  
  470.     /* slot this message in:    */
  471.     base[slots-1].rbmsgNo     = id ;
  472.     base[slots-1].rbmsgLoc    = loc;
  473. }
  474.  
  475. /*
  476.  * FindNet()
  477.  *
  478.  * This function will find the named node.  Stolen from searchNameNet/NETMISC.
  479.  */
  480. int  FindNet(label nm, NetBuffer *nBuf)
  481. {
  482.     int rover;
  483.  
  484.     for (rover = 0; rover < cfg.netSize; rover++) {
  485.         if (netTab[rover].ntflags.in_use &&
  486.             hash(nm) == netTab[rover].ntnmhash) {
  487.             getNet(rover, nBuf);
  488.             if (strCmpU(nBuf->netName, nm) == SAMESTRING)
  489.                 return rover;
  490.         }
  491.     }
  492.     return ERROR;
  493. }
  494.  
  495. /*
  496.  * FindPos()
  497.  *
  498.  * This finds the spot in the shared room array for the node that matches up
  499.  * with the current room.
  500.  */
  501. int FindPos()
  502. {
  503.     int rover;
  504.  
  505.     for (rover = 0; rover < SHARED_ROOMS; rover++)
  506.         if (isSharedRoom(thisNet, rover) &&
  507.                         netRoomSlot(rover) == thisRoom &&
  508.                                 netGen(thisNet, rover)  == roomBuf.rbgen)
  509.             return rover;
  510.  
  511.     return ERROR;
  512. }
  513.  
  514. /*
  515.  * VirtualHandle()
  516.  *
  517.  * This function will handle a message destined for a virt room.
  518.  */
  519. void VirtualHandle()
  520. {
  521.     int Vindex;
  522.  
  523.     if ((Vindex = VirtualShared(thisNet, msgBuf.mbroom)) == ERROR) {
  524.         printf("Virtual room %s not shared with %s, message not saved.\n",
  525.                                 msgBuf.mbroom, netBuf.netName);
  526.         return;
  527.     }
  528.     MARecVirtualRoom(Vindex);
  529. }
  530.  
  531. /*********** These functions stolen & modified from VIRT2.C ***************/
  532.  
  533. extern VirtualRoom *VRoomTab;
  534. extern VirtNet     *VirtNetList;
  535. extern int  VirtSize, VNetSize;
  536. /*
  537.  * MARecVirtualRoom()
  538.  *
  539.  * This function receives a virtual room from another system.
  540.  */
  541. int MARecVirtualRoom(int VirtIndex)
  542. {
  543.     int         VirtNo;
  544.     MSG_NUMBER  rover;
  545.     char        *distance, fn[50];
  546.     extern FILE *upfd;
  547.     extern char *WRITE_ANY;
  548.  
  549.     VirtNo = VirtNetList[thisNet].VirtList[VirtIndex].WhichVirt;
  550.  
  551.     if (VirtNetList[thisNet].VirtList[VirtIndex].mode != PEON) {
  552.         distance = LD_DIR;
  553.         rover = VRoomTab[VirtNo].vrHiLD + 1l;
  554.         VRoomTab[VirtNo].vrChanged |= LD_CHANGE;
  555.     }
  556.     else {
  557.         distance = LOCAL_DIR;
  558.         rover = VRoomTab[VirtNo].vrHiLocal + 1l;
  559.         VRoomTab[VirtNo].vrChanged |= LOC_CHANGE;
  560.     }
  561.     CreateVAName(fn, VirtNo, distance, rover);
  562.  
  563.     if ((upfd = fopen(fn, WRITE_ANY)) != NULL) {
  564.         if (msgBuf.mbauth[0])
  565.             AddVirtualField('A', msgBuf.mbauth);
  566.         if (msgBuf.mbdate[0])
  567.             AddVirtualField('D', msgBuf.mbdate);
  568.         if (msgBuf.mbtime[0])
  569.             AddVirtualField('C', msgBuf.mbtime);
  570.         if (msgBuf.mboname[0])
  571.             AddVirtualField('N', msgBuf.mboname);
  572.         if (msgBuf.mborig[0])
  573.             AddVirtualField('O', msgBuf.mborig);
  574.         if (msgBuf.mbroom[0])
  575.             AddVirtualField('R', msgBuf.mbroom);
  576.         if (msgBuf.mbsrcId[0])
  577.             AddVirtualField('S', msgBuf.mbsrcId);
  578.         if (msgBuf.mbto[0])
  579.             AddVirtualField('T', msgBuf.mbto);
  580.         if (msgBuf.mbOther[0])
  581.             AddVirtualField('P', msgBuf.mbOther);
  582.         if (msgBuf.mbdomain[0])
  583.             AddVirtualField('X', msgBuf.mbdomain);
  584.         if (msgBuf.mbtext[0])
  585.             AddVirtualField('M', msgBuf.mbtext);
  586.         fclose(upfd);
  587.     }
  588.     else
  589.         printf("Unable to open %s!\n", fn);
  590.  
  591.     VirtSummary();
  592.     return 0;
  593. }
  594.  
  595. /*
  596.  * AddVirtualField()
  597.  *
  598.  * This function adds a field to a virtual room message.
  599.  */
  600. void AddVirtualField(char field, char *contents)
  601. {
  602.     fprintf(upfd, "%c%s", field, contents);
  603.     fputc(0, upfd);
  604. }
  605.  
  606. /*
  607.  * VirtualExists()
  608.  *
  609.  * This function returns an index to given room, if exists.
  610.  */
  611. int VirtualExists(label name)
  612. {
  613.     int rover;
  614.  
  615.     for (rover = 0; rover < VirtSize; rover++)
  616.         if (strCmpU(VRoomTab[rover].vrName, name) == SAMESTRING) return rover;
  617.  
  618.     return ERROR;
  619. }
  620.  
  621. /*
  622.  * VirtualShared()
  623.  *
  624.  * This function returns an index into current net's virtual index.
  625.  */
  626. int VirtualShared(int NetNo, label name)
  627. {
  628.     int rover, VirtNo;
  629.  
  630.     if ((VirtNo = VirtualExists(name)) == ERROR) return ERROR;
  631.  
  632.     for (rover = 0; rover < VIRT_LIMIT; rover++)
  633.         if (VirtNetList[NetNo].VirtList[rover].WhichVirt == VirtNo)
  634.             return rover;
  635.     return ERROR;
  636. }
  637.  
  638. /*********** These functions stolen & modified from MSG.C ***************/
  639.  
  640. /*
  641.  * doActualWrite()
  642.  *
  643.  * This should allow automatic bkp of msg file from RAM.
  644.  */
  645. char doActualWrite(whichmsg, mFile, c)
  646. FILE    *whichmsg;
  647. struct mBuf *mFile;
  648. char    c;
  649. {
  650.     MSG_NUMBER temp;
  651.     int toReturn = 0;
  652.  
  653.     if (mFile->sectBuf[mFile->thisChar] == 0xFF)  {
  654.         /* obliterating a msg   */
  655.         toReturn = 1;
  656.     }
  657.  
  658.     mFile->sectBuf[mFile->thisChar]   = c;
  659.  
  660.     mFile->thisChar    = ++mFile->thisChar % MSG_SECT_SIZE;
  661.  
  662.     if (mFile->thisChar == 0) { /* time to write sector out and get next: */
  663.         temp = mFile->thisSector;
  664.         temp *= MSG_SECT_SIZE;
  665.         fseek(whichmsg, temp, 0);
  666.         crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  667.         if (fwrite(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  668.             crashout("?putMsgChar-write fail");
  669.         }
  670.  
  671.         mFile->thisSector = ++mFile->thisSector % cfg.maxMSector;
  672.         temp = mFile->thisSector;
  673.         temp *= MSG_SECT_SIZE;
  674.         fseek(whichmsg, temp, 0);
  675.         if (fread(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  676.             crashout("?putMsgChar-read fail");
  677.         }
  678.         crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  679.     }
  680.     return (char) toReturn;
  681. }
  682.  
  683. /*
  684.  * doFlush()
  685.  *
  686.  * This will do actual writeup for specified msg file.
  687.  */
  688. void doFlush(whichmsg, mFile)
  689. FILE *whichmsg;
  690. struct mBuf *mFile;
  691. {
  692.     long int s;
  693.  
  694.     s = mFile->thisSector;
  695.     s *= MSG_SECT_SIZE;
  696.     fseek(whichmsg, s, 0);
  697.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  698.     if (fwrite(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  699.         crashout("?ctdlmsg.sys write fail");
  700.     }
  701.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  702.     fflush(whichmsg);
  703. }
  704.  
  705. /*
  706.  * flushMsgBuf()
  707.  *
  708.  * This wraps up writing a message to disk, takes into account 2nd msg file if
  709.  * necessary.
  710.  */
  711. void flushMsgBuf()
  712. {
  713.     doFlush(msgfl, &mFile1);
  714.     if (cfg.BoolFlags.mirror)
  715.         doFlush(msgfl2, &mFile2);
  716. }
  717.  
  718. /*
  719.  * putMessage()
  720.  *
  721.  * This function stores a message to disk.
  722.  * Always called before noteMessage() -- newest not ++ed yet.
  723.  * Returns: TRUE on successful save, else FALSE
  724.  */
  725. void PutMessage()
  726. {
  727.     label temp;
  728.     extern char *ALL_LOCALS, *WRITE_LOCALS;
  729.     extern char *R_SH_MARK, *LOC_NET, *NON_LOC_NET;
  730.     char  *s;
  731.  
  732.     startAt(msgfl, &mFile1, cfg.catSector, cfg.catChar);
  733.             /* tell putMsgChar where to write   */
  734.     if (cfg.BoolFlags.mirror)
  735.         startAt(msgfl2, &mFile2, cfg.catSector, cfg.catChar);
  736.  
  737.     putMsgChar(0xFF);   /* start-of-message     */
  738.  
  739.     /* write message ID */
  740.     sPrintf(temp, "%lu", cfg.newest + 1);
  741.     AddField(0, temp);
  742.  
  743.     /* write date:      */
  744.     if (msgBuf.mbdate[0]) {
  745.         AddField('D', msgBuf.mbdate);
  746.     }
  747.     else {
  748.         AddField('D', "????");
  749.     }
  750.  
  751.     /* write time:      */
  752.     if (msgBuf.mbtime[0]) {
  753.         AddField('C', msgBuf.mbtime);
  754.     }
  755.     else {
  756.         AddField('C', "!!!!");
  757.     }
  758.  
  759.     /* write author's name out: */
  760.     if (msgBuf.mbauth[0]) {
  761.         AddField('A', msgBuf.mbauth);
  762.     }
  763.  
  764.     /* write room name out:     */
  765.     AddField('R', msgBuf.mbroom);
  766.  
  767.     if (msgBuf.mbto[0]) {       /* private message -- write addressee   */
  768.         AddField('T', msgBuf.mbto);
  769.     }
  770.  
  771.     if (msgBuf.mbaddr[0]) {     /* net message routing  */
  772.         if (strCmpU(msgBuf.mbaddr, R_SH_MARK  ) == SAMESTRING ||
  773.                 strCmpU(msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING) {
  774.             AddField('N', msgBuf.mboname);
  775.             if (msgBuf.mborig[0])   {
  776.                 AddField('O', msgBuf.mborig);
  777.             }
  778.             roomTab[thisRoom].rtlastNet = cfg.newest + 1;
  779.         }
  780.         else if (strCmpU(msgBuf.mbaddr, LOC_NET    ) == SAMESTRING) {
  781.             AddField('N', msgBuf.mboname);
  782.             if (msgBuf.mborig[0])   {
  783.                 AddField('O', msgBuf.mborig);
  784.             }
  785.         }
  786.  
  787.         sPrintf(temp, "%s%d", msgBuf.mbaddr, thisNet);
  788.         AddField('Q', temp);
  789.     }
  790.     else {
  791.         if (msgBuf.mboname[0]) {
  792.             AddField('N', msgBuf.mboname);
  793.         }
  794.         if (msgBuf.mborig[0])   {
  795.             AddField('O', msgBuf.mborig);
  796.         }
  797.     }
  798.  
  799.     if (msgBuf.mbdomain[0])   {
  800.         AddField('X', msgBuf.mbdomain);
  801.     }
  802.  
  803.     if (msgBuf.mbsrcId[0])   {
  804.         AddField('S', msgBuf.mbsrcId);
  805.     }
  806.  
  807.     if (msgBuf.mbOther[0])   {
  808.         AddField('P', msgBuf.mbOther);
  809.     }
  810.  
  811.     /* write message text by hand because it would overrun AddField buffer: */
  812.     putMsgChar('M');    /* M-for-message.       */
  813.     for (s = msgBuf.mbtext;  *s;  s++) putMsgChar(*s);
  814.  
  815.     putMsgChar(0);      /* null to end text     */
  816.     flushMsgBuf();
  817.  
  818. }
  819.  
  820. /*
  821.  * AddField()
  822.  *
  823.  * This adds a field to the message base.
  824.  */
  825. void AddField(field, fValue)
  826. int field;
  827. char *fValue;
  828. {
  829.     if (field) putMsgChar(field);
  830.     while (*fValue) putMsgChar(*fValue++);
  831.     putMsgChar(0);      /* End field. */
  832. }
  833.  
  834. /*
  835.  * putMsgChar()
  836.  *
  837.  * This function writes successive message chars to disk.
  838.  * Globals:     thisChar=       thisSector=
  839.  * Returns:     ERROR if problems else TRUE.
  840.  */
  841. int putMsgChar(c)
  842. int c;
  843. {
  844.     int  toReturn;
  845.     int  count1, count2;
  846.  
  847.     toReturn = TRUE;
  848.     count1 = doActualWrite(msgfl, &mFile1, c);
  849.     if (cfg.BoolFlags.mirror) {
  850.         count2 = doActualWrite(msgfl2, &mFile2, c);
  851.         if (count1 != count2) printf("Mirror msg count discrepancy!");
  852.     }
  853.     if (count1)
  854.         ++cfg.oldest;
  855.     return toReturn;
  856. }
  857.  
  858. static label SearchResult;
  859. static char  *SearchTarget, GetAlias;
  860. /*
  861.  * UseNetAlias()
  862.  *
  863.  * This function will find a usenet alias or the converse.
  864.  */
  865. char *UseNetAlias(char *Name, char FindAlias)
  866. {
  867.     void *EatTrans();
  868.     SListBase Dummy = { NULL, NULL, NULL, NULL, EatTrans };
  869.     SYS_FILE fn;
  870.     char *c;
  871.  
  872.     SearchResult[0] = 0;
  873.     SearchTarget = Name;
  874.     if (!FindAlias) while ((c = strchr(Name, ' ')) != NULL) *c = '_';
  875.     makeSysName(fn, "st-alias.sys", &cfg.roomArea);
  876.     GetAlias = FindAlias;
  877.     MakeList(&Dummy, fn, NULL); /* CHEAT!  WHEEEEEE! */
  878.     if (strLen(SearchResult) == 0) return NULL;
  879.     return SearchResult;
  880. }
  881.  
  882. /*
  883.  * EatTrans()
  884.  *
  885.  * This function will eat a line of for the alias mapping.
  886.  */
  887. void *EatTrans(char *line)
  888. {
  889.     char *c;
  890.  
  891.     if ((c = strchr(line, ' ')) != NULL) {
  892.         *c = 0;
  893.         if (GetAlias) {         /* check second field */
  894.             if (strCmpU(c + 1, SearchTarget) == SAMESTRING) {
  895.                 strCpy(SearchResult, line);
  896.             }
  897.         }
  898.         else {                  /* check first field */
  899.             if (strCmpU(line, SearchTarget) == SAMESTRING) {
  900.                 strCpy(SearchResult, c + 1);
  901.             }
  902.         }
  903.     }
  904.     return NULL;
  905. }
  906.  
  907. /*
  908.  * FindRouteSlot()
  909.  *
  910.  * This function will find the slot of routing node.  If found, netTemp will
  911.  * contain the new slot, as will RouteSlot.
  912.  */
  913. int FindRouteSlot()
  914. {
  915.     /*
  916.      * first check to see if we're the direct (final) link, either
  917.      * expressly or because the route is outdated.
  918.      */
  919.     if (!DirectRoute(&netTemp)) /* expressly?   */
  920.         getNet((RouteSlot = netTemp.nbRoute), &netTemp);
  921.  
  922.     return RouteSlot;
  923. }
  924.  
  925. /*
  926.  * DirectRoute()
  927.  *
  928.  * This will discover if we directly or indirectly talk to this node.
  929.  */
  930. char DirectRoute(NetBuffer *n)
  931. {
  932.     return (char) (n->nbRoute == -1 ||  /* expressly?   */
  933.         !netTab[n->nbRoute].ntflags.in_use ||    /* outdated?    */
  934.         netTab[n->nbRoute].ntGen != n->nbRouteGen);/* outdated?*/
  935. }
  936.  
  937. /*
  938.  * getNetChar()
  939.  *
  940.  * This gets a character from a network temporary file.
  941.  */
  942. int getNetChar()
  943. {
  944.     return -1;          /* actually, this should never be called.       */
  945. }
  946.  
  947. /*
  948.  * SepNameSystem()
  949.  *
  950.  * This will parse an Other Recipient spec.
  951.  */
  952. char SepNameSystem(char *string, char *person, char *system, NetBuffer *buf)
  953. {
  954.     char *c;
  955.     int  n;
  956.     char work[NAMESIZE * 3];    /* should be sufficient */
  957.  
  958.     strCpy(work, string);
  959.     if ((c = strchr(work, '@')) == NULL)
  960.         return NOT_SYSTEM;
  961.  
  962.     /* find leading spaces of "name @ system" format */
  963.     for (n = 1; c[n] == ' ' && c[n]; n++)
  964.         ;
  965.  
  966.     if (strLen(c + n) >= NAMESIZE)
  967.         return BAD_FORMAT;
  968.  
  969.     strCpy(system, c + n);
  970.     if (searchNameNet(c + n, buf) == ERROR)  /* bad - set signal of it */
  971.         return NO_SYSTEM;
  972.  
  973.     *c = 0;
  974.     CleanEnd(work);     /* kill trailing spaces */
  975.     if (strLen(work) >= NAMESIZE)
  976.         return BAD_FORMAT;
  977.  
  978.     strCpy(person, work);
  979.  
  980.     return IS_SYSTEM;
  981. }
  982.  
  983. #define WeServe(x)      SearchList(&Serves, x)
  984. extern SListBase Serves;
  985. /*
  986.  * LocalName()
  987.  *
  988.  * This takes a string of form <system> _ <domain> and attempts to discover if
  989.  * this domain mapped system is actually a local.  This is used when we're
  990.  * sending mail and are trying to find out if a Who Else override needs to be
  991.  * generated.  Ugly kludge, but, hey, that's what programming's all about, eh?
  992.  */
  993. char *LocalName(char *system)
  994. {
  995.     char *domain, *System;
  996.  
  997.     if ((domain = strchr(system, '_')) == NULL) return system;
  998.     domain += 2;        /* always preceded by a space -- or so we assume */
  999.  
  1000.     if (strCmpU(domain, cfg.codeBuf + cfg.nodeDomain) == SAMESTRING ||
  1001.              WeServe(domain) != NULL) {
  1002.         System = strdup(system);
  1003.         if ((domain = strchr(System, ' ')) == NULL)
  1004.             return system;      /* should never happen, though */
  1005.         *domain = NULL;
  1006.         if (searchNameNet(System, &netTemp) != ERROR) {
  1007.             free(System);
  1008.             return netTemp.netName;
  1009.         }
  1010.         free(System);
  1011.     }
  1012.     return system;
  1013. }
  1014.  
  1015. /*
  1016.  * mFormat()
  1017.  *
  1018.  * This function formats a string to modem and console.
  1019.  */
  1020. void mFormat(char *string)
  1021. {
  1022.     char wordBuf[MAXWORD];
  1023.     int  i;
  1024.  
  1025.     for (i = 0;  string[i]; ) {
  1026.         i = getWord(wordBuf, string, i, MAXWORD);
  1027.         putWord(wordBuf);
  1028.     }
  1029. }
  1030.  
  1031. /*
  1032.  * getWord()
  1033.  *
  1034.  * This function fetches one word from current message.
  1035.  */
  1036. int getWord(char *dest, char *source, int offset, int lim)
  1037. {
  1038.     int i, j;
  1039.  
  1040.     /* skip leading blanks if any */
  1041.     for (i = 0;  source[offset+i] ==' ' && i < lim - 1;  i++);
  1042.  
  1043.     /* step over word */
  1044.     for (;
  1045.  
  1046.         source[offset+i]   != ' '     &&
  1047.         i       <  lim - 1 &&
  1048.         source[offset+i]   != 0;
  1049.  
  1050.         i++
  1051.     );
  1052.  
  1053.     if (source[offset + i - 1] != '\n')
  1054.     /* pick up any trailing blanks */
  1055.     for (;  source[offset+i]==' ' && i<lim - 1;  i++);
  1056.  
  1057.     /* copy word over */
  1058.     for (j = 0; j < i; j++)  dest[j] = source[offset+j];
  1059.     dest[j] = 0;        /* null to tie off string */
  1060.  
  1061.     return(offset+i);
  1062. }
  1063.  
  1064. /*
  1065.  * putWord()
  1066.  *
  1067.  * This function writes one word to modem & console.
  1068.  */
  1069. void putWord(char *st)
  1070. {
  1071.     char *s;
  1072.     int  newColumn;
  1073.     static char prevChar = 0;
  1074.  
  1075.     for (newColumn = crtColumn, s = st;  *s; s++)   {
  1076.         if (*s != TAB) {
  1077.             if (*s == '\b') newColumn--;
  1078.             else ++newColumn;
  1079.         }
  1080.         else    while (++newColumn % 8);
  1081.     }
  1082.     if (newColumn > termWidth) {
  1083.         fprintf(upfd, "\n");
  1084.         crtColumn = 1;
  1085.     }
  1086.  
  1087.     for (;  *st;  st++) {
  1088.  
  1089.         if (*st != TAB) {
  1090.             if (*st == '\b') crtColumn--;
  1091.             else ++crtColumn;
  1092.         }
  1093.         else    while (++crtColumn % 8);
  1094.  
  1095.         /* worry about words longer than a line:        */
  1096.         if (crtColumn > termWidth) {
  1097.             fprintf(upfd, "\n");
  1098.             crtColumn = 1;
  1099.         }
  1100.  
  1101.         if (*st == '\n' && EOP) {
  1102.             fprintf(upfd, "\n");
  1103.             crtColumn = 1;
  1104.         }
  1105.         else if (prevChar!=NEWLINE  ||  (*st > ' ')) {
  1106.             putc(*st, upfd); prevChar = *st;
  1107.             if (*st > ' ') EOP = FALSE;
  1108.         }
  1109.         else {
  1110.             fprintf(upfd, "\n");
  1111.             crtColumn = 1;
  1112.             if (*st == '\n' && !EOP) {
  1113.                 fprintf(upfd, "\n");
  1114.                 crtColumn = 1;
  1115.             }
  1116.             else putc(*st, upfd), prevChar = *st;
  1117.             EOP = TRUE;
  1118.         }
  1119.     }
  1120. }
  1121.  
  1122. /*
  1123. * TranslateFilename()
  1124. *
  1125. * This does translations on a filename.  This is used for embedding dates
  1126. * or numbers into a filename.
  1127. */
  1128. void TranslateFilename(char *realfn, char *fn)
  1129.   {
  1130.   int year, day, hours, minutes;
  1131.   char *month;
  1132.   getCdate(&year, &month, &day, &hours, &minutes);
  1133.   do
  1134.     {
  1135.     *realfn = *fn;
  1136.     if (*fn == '%')
  1137.       {
  1138.       fn++;
  1139.       switch (*fn)
  1140.         {
  1141.         case 'm':
  1142.         case 'M':
  1143.         sPrintf(realfn, "%s", month);
  1144.         break;
  1145.         case 'y':
  1146.         case 'Y':
  1147.         sPrintf(realfn, "%d", year);
  1148.         break;
  1149.         default:
  1150.         sPrintf(realfn, "%c", *fn);
  1151.         break;
  1152.  
  1153.         }
  1154.       while (*(realfn + 1))
  1155.       realfn++;
  1156.  
  1157.       }
  1158.     realfn++;
  1159.  
  1160.     }
  1161.   while (*fn++);
  1162.  
  1163.   }
  1164.  
  1165. void netResult(char *msg)
  1166.   {
  1167.   printf("%s\n",msg);
  1168.   }
  1169.  
  1170. char *MonthTab[] =
  1171.     {
  1172.     "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
  1173.     "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
  1174.  
  1175.     };
  1176.  
  1177. char *KeyWords[] =
  1178.     {
  1179.     "TODAY", "YESTERDAY"
  1180.  
  1181.     };
  1182.  
  1183. char DayPMonth[] =
  1184.     {
  1185.     31,28,31,30,31,30,31,31,30,31,30,31
  1186.  
  1187.     };
  1188.  
  1189.  
  1190. /*
  1191.  * getCdate()
  1192.  *
  1193.  * This retrieves system date and returns in the parameters.
  1194. */
  1195.   void getCdate(int *year, char **month, int *day, int *hours, int *minutes)
  1196.     {
  1197.     int mon, seconds, milli;
  1198.     getRawDate(year, &mon, day, hours, minutes, &seconds, &milli);
  1199.     *year -= 1900;
  1200.     *month = MonthTab[mon];
  1201.  
  1202.     }
  1203.  
  1204. void  Do_Stack_Check(void);
  1205.  
  1206.  
  1207. #define LeapYear(x)     ((x % 4) ? FALSE : ((year % 100) ? TRUE : FALSE))
  1208. /************************************************************************/
  1209. /*      ReadDate() interprets the string and returns it in seconds      */
  1210. /************************************************************************/
  1211. int ReadDate(char *date, long *RetTime)
  1212.   {
  1213.   int rover, found, keyword = -1;
  1214.   int   year, month, day, hours, minutes, seconds, milli;
  1215.   label mon;
  1216.   char *d = date;
  1217.   char  darray[6];              /* see format for utpack() */
  1218.   Do_Stack_Check();
  1219.   if (strLen(date) == 0) return FALSE;
  1220.   if (isdigit(date[0]))
  1221.     {
  1222.     darray[0] = (char) (atoi(date) + 1900 - 1970);
  1223.     while (isdigit(*date)) date++;
  1224.  
  1225.     }
  1226.   else
  1227.     {
  1228.     getRawDate(&year, &month, &day, &hours, &minutes,
  1229.     &seconds, &milli);
  1230.     year -= 1970;
  1231.     darray[0] = (char) year;
  1232.     darray[1] = (char) month;
  1233.     darray[2] = (char) day;
  1234.  
  1235.     }
  1236.   for (rover = 0; isalpha(*date); date++, rover++)mon[rover] = toUpper(*date);
  1237.   mon[rover] = 0;
  1238.   if (rover == 0)
  1239.     {
  1240.     if( isdigit(d[0]) )
  1241.       {
  1242.       *RetTime = CurAbsolute() - ( atol(d)*86400l);
  1243.       return TRUE;
  1244.       }
  1245.     return ERROR;
  1246.     };
  1247.   for (found = rover = 0; rover < NumElems(MonthTab); rover++)
  1248.   if (strncmp(mon, MonthTab[rover], strLen(mon)) == SAMESTRING)
  1249.     {
  1250.     found++;
  1251.     darray[1] = (char) (rover + 1);
  1252.  
  1253.     }
  1254.   if (found != 1)
  1255.     {
  1256.     for (keyword = -1, rover = 0; rover < NumElems(KeyWords); rover++)
  1257.     if (strncmp(mon, KeyWords[rover], strLen(mon)) == SAMESTRING)
  1258.       {
  1259.       keyword = rover;
  1260.  
  1261.       }
  1262.     if (keyword == -1)
  1263.     return ERROR;
  1264.     else
  1265.       {
  1266.       switch(keyword)
  1267.         {
  1268.         case 0: /* TODAY */
  1269.         break;
  1270.         case 1: /* YESTERDAY */
  1271.         --darray[2];
  1272.         if (!darray[2])
  1273.           {
  1274.           --darray[1];
  1275.           if (!darray[1])
  1276.             {
  1277.             darray[1] = 12;
  1278.             --darray[0];
  1279.  
  1280.             }
  1281.           darray[2] = DayPMonth[darray[1] - 1];
  1282.           if (darray[1] == 2 && LeapYear(darray[0]))
  1283.           darray[2] = 29;
  1284.  
  1285.           }
  1286.         break;
  1287.  
  1288.         }
  1289.  
  1290.       }
  1291.  
  1292.     }
  1293.   if ((keyword == -1) && ((darray[2] = (char) atoi(date)) == 0)) return ERROR;
  1294.   darray[3] = 0;
  1295.   darray[4] = 0;
  1296.   darray[5] = 0;
  1297.   *RetTime = utpack(darray);
  1298.   return TRUE;
  1299.  
  1300.   }
  1301.  
  1302. /************************************************************************/
  1303. /*      CurAbsolute() current time in absolute terms.                   */
  1304. /************************************************************************/
  1305. long CurAbsolute()
  1306.   {
  1307.   Do_Stack_Check();
  1308.   return time(NULL);
  1309.  
  1310.   }
  1311.